/**
 * 1.创建安全的闭包环境
 * 2.为模块管理器对象提供一个module方法
 */
// 向闭包中传入模块管理器对象F(~屏蔽压缩文件时，前面漏写;报错)
~(function(F) {
    // 模块缓存器。存储已创建模块
    var moduleCache = {},
        setModule = function(moduleName, params, cb) {//设置模块并执行模块构造函数
            var _module, fn;
            if (moduleCache[moduleName]) {
                _module = moduleCache[moduleName];
                _module.status = 'loaded';
                _module.exports = cb ? cb.apply(_module, params) : null;
                while(fn = _module.onload.shift()) {
                    fn(_module.exports);
                }
            } else {
                cb && cb.apply(null, params);                    
            }
        },
        loadModule = function(moduleName, cb) {
            var _module;
            if (moduleCache[moduleName]) {
                _module = moduleCache[moduleName];
                if (_module.status === 'loaded') {
                    setTimeout(cb(_module.exports), 0);
                } else {
                    _module.onload.push(cb);
                }
            } else {
                moduleCache[moduleName] = {
                    moduleName: moduleName,
                    status: 'loading',
                    exports: null,
                    onload: [cb]
                };
                loadScript(getUrl(moduleName));
            }
        },
        getUrl = function(moduleName) {
            return String(moduleName).replace(/\.js$/g, '') + '.js';
        },
        loadScript = function(src) {
            var _script = document.createElement('script');
            _script.type = 'text/javascript';//文件类型
            _script.charset = 'UTF-8';//确认编码
            _script.async = true;//异步加载
            _script.src = src;//文件路径
            document.getElementsByTagName('head')[0].appendChild(_script);//插入页面
        };
})(
    (function() {
        // 创建模块管理器对象F，并保存在全局作用域中
        return window.F = {};
    })()
);

/**
 * 创建或调用模块方法
 * @param {*} url 模块url
 * @param {*} modDeps 依赖模块
 * @param {*} modCb 模块主函数
 */
F.module = function(url, modDeps, modCb) {
    var args = [].slice.call(arguments),//参数转化为数组
        cb = args.pop(),//获取模块构造函数，参数数组中最后一个参数成员
        deps = (args.length && args[args.length - 1] instanceof Array) ? args.pop() : [],//获取依赖模块，紧邻回调函数参观，且数据类型为数组
        url = args.length ? args.pop() : null,
        params = [],//依赖模块序列
        depsCount = 0,//未加载的依赖模块数量统计
        i = 0,//依赖模块序列中索引值
        len;//依赖模块序列长度
    if (len = deps.length) {//获取依赖模块长度
        while(i < len) {//遍历依赖模块
            (function(i) {//闭包保存i
                depsCount++;//增加未加载依赖模块数量统计
                loadModule(deps[i], function(mod) {//异步加载依赖模块
                    params[i] = mod;//依赖模块序列中添加依赖模块接口引用
                    depsCount--;//依赖模块加载完成，依赖模块数量统计减一
                    if (depsCount === 0) {//如果依赖模块全部加载
                        setModule(url, params, cb);//在模块缓存其中矫正该模块，并执行构造函数
                    }
                });
            })(i);
            i++;
        }
    } else {//无依赖模块，直接执行回调函数
        //在模块缓存器中矫正该模块，并执行构造函数
        setModule(url, [], cb);
    }
}

F.module('lib/dom', function() {
    return {
        g: function(id) {
            return document.getElementById(id);
        },
        html: function(id, html) {
            if (html)
                this.g(id).innerHTML = html;
            else
                return this.g(id).innerHTML;
        }
    };
});

F.module('lib/event', ['lib/dom'], function(dom) {
    var events = {
        on: function(id, type, fn) {
            dom.g(id)['on' + type] = fn;
        }
    };
    return events;
});
